package com.chengcang.admin.modules.busi.service.impl;

import cn.hutool.core.util.NumberUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.chengcang.admin.modules.busi.dto.orderSnapshotDTO.BusiOrderAddressSnapshotDTO;
import com.chengcang.admin.modules.busi.dto.orderSnapshotDTO.BusiOrderInvoiceHeadSnapshotDTO;
import com.chengcang.admin.modules.busi.service.*;
import com.chengcang.admin.modules.sys.dao.SysOrderProductSnapshotDao;
import com.chengcang.admin.modules.sys.dao.SysOrderTenantSnapshotDao;
import com.chengcang.admin.modules.sys.dto.*;
import com.chengcang.admin.modules.sys.dto.orderSnapshotDTO.SysOrderProductSnapshotDTO;
import com.chengcang.admin.modules.sys.dto.orderSnapshotDTO.SysOrderTenantSnapshotDTO;
import com.chengcang.admin.modules.sys.entity.orderSnapshotEntity.SysOrderTenantSnapshotEntity;
import com.chengcang.admin.modules.sys.service.*;
import com.chengcang.common.enums.DataTypeEnum;
import com.chengcang.admin.common.utils.DicTransLateUtil;
import com.chengcang.admin.modules.busi.dao.BusiDemandDao;
import com.chengcang.admin.modules.busi.dao.BusiOrderDao;
import com.chengcang.admin.modules.busi.dto.*;
import com.chengcang.admin.modules.busi.entity.BusiDemandEntity;
import com.chengcang.admin.modules.busi.entity.BusiOrderEntity;
import com.chengcang.admin.modules.security.user.SecurityUser;
import com.chengcang.admin.modules.sys.dao.SysDictTypeDao;
import com.chengcang.admin.modules.sys.dao.SysTenantDao;
import com.chengcang.admin.modules.sys.entity.SysDictTypeEntity;
import com.chengcang.admin.modules.sys.entity.SysTenantEntity;
import com.chengcang.common.constant.Constant;
import com.chengcang.common.exception.CustomException;
import com.chengcang.common.page.PageData;
import com.chengcang.common.service.impl.CrudServiceImpl;
import com.chengcang.common.utils.ConvertUtils;
import com.chengcang.common.utils.DateUtils;
import com.chengcang.common.utils.SnowFlakeUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.MessageFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author zhanli
 * @since 1.0.0 2023-01-10
 */
@Service
@Slf4j
public class BusiOrderServiceImpl extends CrudServiceImpl<BusiOrderDao, BusiOrderEntity, BusiOrderDTO> implements BusiOrderService {


    @Resource
    private BusiOrderAddressSnapshotService addrShotService;

    @Resource
    private BusiAddressService addressService;

    @Resource
    private BusiDemandAddressSnapshotService demandAddressSnapshotService;

    @Resource
    private BusiOrderInvoiceHeadSnapshotService invoiceHeadSnapshotService;

    @Resource
    private BusiInvoiceHeadService busiInvoiceHeadService;

    @Resource
    private BusiDemandInvoiceHeadSnapshotService demandInvoiceHeadSnapshotService;

    @Resource
    private SysOrderProductSnapshotService productSnapshotService;

    @Resource
    private SysOrderProductSnapshotDao productSnapshotDao;

    @Resource
    private SysProductService sysProductService;

    @Resource
    private BusiDemandProductSnapshotService demandProductSnapshotService;

    @Autowired
    private BusiDemandService busiDemandService;

    @Autowired
    private BusiDemandDao busiDemandDao;

    @Autowired
    private BusiOrderDao busiOrderDao;

    @Autowired
    private SysDictDataService sysDictDataService;

    @Autowired
    private SysTenantDao sysTenantDao;

    @Autowired
    private SysOrderTenantSnapshotDao tenantSnapshotDao;

    @Autowired
    private SysTenantService tenantService;

    @Autowired
    private BusiDemandTenantSnapshotService demandTenantSnapshotService;

    @Autowired
    private SysOrderTenantSnapshotService orderTenantSnapshotService;

    @Autowired
    private BusiDemandPerformanceSnapshotService busiDemandPerformanceSnapshotService;

    @Autowired
    private SysDictTypeDao sysDictTypeDao;

    @Autowired
    private SysTenantService sysTenantService;

    private static final String DATAtIME_FORMAT_PARTTRN = "yyyy-MM-dd HH:mm:ss";

    @Override
    public QueryWrapper<BusiOrderEntity> getWrapper(Map<String, Object> params) {
        String id = (String) params.get("id");
        //订单或需求编号
        QueryWrapper<BusiOrderEntity> wrapper = new QueryWrapper<>();
        wrapper.eq(StringUtils.isNotBlank(id), "id", id);
        return wrapper;
    }

    @Override
    public BusiOrderInfoDTO detail(Long id) {
        BusiOrderDTO busiOrderDTO = this.get(id);
        Optional.ofNullable(busiOrderDTO).orElseThrow(() -> new CustomException("未找到对应的订单信息！"));
        BusiOrderInfoDTO result = new BusiOrderInfoDTO();
        BeanUtils.copyProperties(busiOrderDTO, result);
        //获取地址信息
        BusiOrderAddressSnapshotDTO addressSnapshotDTO = addrShotService.get(busiOrderDTO.getAddressId());
        if (!Objects.isNull(addressSnapshotDTO)) {
            BeanUtils.copyProperties(addressSnapshotDTO, result);
            SysTenantEntity sysTenantEntity = sysTenantDao.selectById(addressSnapshotDTO.getTenantId());
            if (!Objects.isNull(sysTenantEntity)) {
                result.setTenantName(sysTenantEntity.getName());
                result.setAddressMobile(addressSnapshotDTO.getAddressMobile());
            }

        }
        //获取发票信息
        BusiOrderInvoiceHeadSnapshotDTO headSnapshotDTO = invoiceHeadSnapshotService.get(busiOrderDTO.getInvoiceHeadId());
        if (!Objects.isNull(headSnapshotDTO)) {
            BeanUtils.copyProperties(headSnapshotDTO, result);
            result.setInvoiceTypeName(sysDictDataService.getValue(DataTypeEnum.INVOICE_TYPE, String.valueOf(result.getInvoiceType())));
        }
        //获取商品信息
        SysOrderProductSnapshotDTO productSnapshotDTO = productSnapshotService.get(busiOrderDTO.getProductId());
        if (!Objects.isNull(productSnapshotDTO)) {
            BeanUtils.copyProperties(productSnapshotDTO, result);
            result.setName(productSnapshotDTO.getName());
        }
        //绑定需求信息
        BusiDemandDTO busiDemandDTO = busiDemandService.getByDemandNo(busiOrderDTO.getDemandNo());
        if (!Objects.isNull(busiDemandDTO)) {
            result.setProductUnit(null);
            BeanUtils.copyProperties(busiDemandDTO, result);
        }
        //字典处理
        try {
            BeanUtils.copyProperties(DicTransLateUtil.translate(result, true, BusiOrderInfoDTO.class), result);
        } catch (Exception e) {
            log.error("字典转换异常", e);
        }
        return result;
    }

    @Override
    @Transactional
    public void deliver(BusiOrderDTO dto) {
        if (dto.getStatus() == 1) throw new CustomException("禁止重复发货");
        //更改需求状态, 履约量
//        BusiDemandEntity busiDemandEntity = busiDemandDao.selectOne(new LambdaQueryWrapper<BusiDemandEntity>().eq(BusiDemandEntity::getDemandNo, dto.getDemandNo()));
//        Optional.ofNullable(busiDemandEntity).orElseThrow(() -> new RuntimeException(MessageFormat.format("该需求[{0}]不存在", dto.getDemandNo())));
//        BigDecimal totalNum = busiDemandEntity.getAlreadySupplyNum().add(dto.getSupplyNum());
//        if (busiDemandEntity.getDemandStatus() == 1) {
//            busiDemandEntity.setAlreadySupplyNum(totalNum.max(busiDemandEntity.getDemandTotal()));
//            busiDemandEntity.setDemandStatus(busiDemandEntity.getAlreadySupplyNum().equals(busiDemandEntity.getDemandTotal()) ? 2 : 1);
//        }
//        busiDemandDao.update(busiDemandEntity, new LambdaQueryWrapper<BusiDemandEntity>().eq(BusiDemandEntity::getDemandNo, busiDemandEntity.getDemandNo()));
        //修改订单状态, 1:已发货, 2月7日 根据产品和测试要求修改，为只有 代发货，已发货状态。
        dto.setStatus(1);
        this.update(dto);

    }

    @Override
    public Page<BusiOrderDTO> getDemandPage(Map<String, Object> params) {
        Page<BusiOrderDTO> busiOrderDTOPage;
        QueryWrapper<BusiOrderEntity> queryWrapper = new QueryWrapper<>();
        //需求方
        queryWrapper.eq(SecurityUser.getTenantId() != null && SecurityUser.getTenantId() != 1L, "demand_id", SecurityUser.getTenantId());
        params.forEach((key, value) -> {
            boolean flag = key.equals("id") || key.equals("source_type") || key.equals("type") || key.equals("status");
            queryWrapper.eq(flag, key, value);
        });
        if (params.get("beginDate") != null && params.get("endDate") != null) {
            queryWrapper.ge("create_date", DateUtils.getMinDataTime((String) params.get("beginDate"), DATAtIME_FORMAT_PARTTRN))
                    .le("create_date", DateUtils.getMaxDataTime((String) params.get("endDate"), DATAtIME_FORMAT_PARTTRN));
        }
        Object order = params.get(Constant.ORDER_FIELD);
        queryWrapper.and(params.get("order_no") != null, qr -> {
            qr.eq("order_no", params.get("order_no")).or().eq("demand_no", params.get("order_no"));
        });
        queryWrapper.orderBy(order == null, false, "create_date");
        queryWrapper.orderBy(order != null, params.get(Constant.ORDER) == null, (String) order);
        Page<BusiOrderEntity> busiOrderEntityPage = busiOrderDao.selectPage(new Page<>(Long.parseLong((String) params.get(Constant.PAGE)),
                Long.parseLong((String) params.get(Constant.LIMIT))), queryWrapper);
        dictProcess(busiOrderEntityPage);
        busiOrderDTOPage = new Page<>();
        BeanUtils.copyProperties(busiOrderEntityPage, busiOrderDTOPage);
        return busiOrderDTOPage;
    }

    @Override
    public Page<BusiOrderDTO> getAllPage(Map<String, Object> params) {
        Page<BusiOrderDTO> busiOrderDTOPage;
        QueryWrapper<BusiOrderEntity> queryWrapper = new QueryWrapper<>();
        Long tenantId = SecurityUser.getTenantId();
        queryWrapper.and(Wrapper -> Wrapper.eq(
                "demand_id", tenantId).or().eq("supply_id", tenantId)
        );
        params.forEach((key, value) -> {
            boolean flag = key.equals("id") || key.equals("source_type") || key.equals("type") || key.equals("status");
            queryWrapper.eq(flag, key, value);
        });
        if (params.get("beginDate") != null && params.get("endDate") != null) {
            queryWrapper.ge("create_date", DateUtils.getMinDataTime((String) params.get("beginDate"), DATAtIME_FORMAT_PARTTRN))
                    .le("create_date", DateUtils.getMaxDataTime((String) params.get("endDate"), DATAtIME_FORMAT_PARTTRN));
        }
        Object order = params.get(Constant.ORDER_FIELD);
        queryWrapper.and(params.get("order_no") != null, qr -> {
            qr.eq("order_no", params.get("order_no")).or().eq("demand_no", params.get("order_no"));
        });
        queryWrapper.orderBy(order == null, false, "create_date");
        queryWrapper.orderBy(order != null, params.get(Constant.ORDER) == null, (String) order);
        Page<BusiOrderEntity> busiOrderEntityPage = busiOrderDao.selectPage(new Page<>(Long.parseLong((String) params.get(Constant.PAGE)),
                Long.parseLong((String) params.get(Constant.LIMIT))), queryWrapper);
        dictProcess(busiOrderEntityPage);
        busiOrderDTOPage = new Page<>();
        BeanUtils.copyProperties(busiOrderEntityPage, busiOrderDTOPage);
        return busiOrderDTOPage;
    }

    protected void dictProcess(Page<BusiOrderEntity> pageData) {
        //字典处理
        List<Long> ids = pageData.getRecords().stream().map(BusiOrderEntity::getDemandId).distinct().collect(Collectors.toList());
        ids.addAll(pageData.getRecords().stream().map(BusiOrderEntity::getSupplyId).distinct().collect(Collectors.toList()));
        Map<Long, SysOrderTenantSnapshotEntity> tenantMap = tenantSnapshotDao.selectList(new LambdaQueryWrapper<SysOrderTenantSnapshotEntity>()
                        .in(!ids.isEmpty(), SysOrderTenantSnapshotEntity::getId, ids))
                .stream().collect(Collectors.toMap(SysOrderTenantSnapshotEntity::getId, item -> {
                    return item;
                }));
        Map<String, String> orderStatus = this.dict(DataTypeEnum.ORDER_STATUS.getKey());
        for (BusiOrderEntity dto : pageData.getRecords()) {
            try {
                BeanUtils.copyProperties(DicTransLateUtil.translate(dto, true, BusiOrderEntity.class), dto);
                if (dto.getStatus() != null && orderStatus != null) {
                    dto.setStatusName(orderStatus.get(dto.getStatus().toString()));
                }
            } catch (Exception e) {
                log.error(e.getMessage(), e);
                throw new CustomException("字典转换异常！");
            }
        }
    }

    @Override
    public Page<BusiOrderDTO> getSupplyPage(Map<String, Object> params) {
        Page<BusiOrderDTO> busiOrderDTOPage;
        QueryWrapper<BusiOrderEntity> queryWrapper = new QueryWrapper<>();
        //需求方
        queryWrapper.eq(SecurityUser.getTenantId() != null, "supply_id", SecurityUser.getTenantId());
        params.forEach((key, value) -> {
            boolean flag = key.equals("id") || key.equals("source_type") || key.equals("type") || key.equals("status");
            queryWrapper.eq(flag, key, value);
        });
        if (params.get("beginDate") != null && params.get("endDate") != null) {
            queryWrapper.ge("create_date", DateUtils.getMinDataTime((String) params.get("beginDate"), DATAtIME_FORMAT_PARTTRN))
                    .le("create_date", DateUtils.getMaxDataTime((String) params.get("endDate"), DATAtIME_FORMAT_PARTTRN));
        }
        Object order = params.get(Constant.ORDER_FIELD);
        queryWrapper.and(params.get("order_no") != null, qr -> {
            qr.eq("order_no", params.get("order_no")).or().eq("demand_no", params.get("order_no"));
        });
        queryWrapper.orderBy(order == null, false, "create_date");
        queryWrapper.orderBy(order != null, params.get(Constant.ORDER) == null, (String) order);
        Page<BusiOrderEntity> busiOrderEntityPage = busiOrderDao.selectPage(new Page<>(Long.parseLong((String) params.get(Constant.PAGE)),
                Long.parseLong((String) params.get(Constant.LIMIT))), queryWrapper);
        dictProcess(busiOrderEntityPage);
        busiOrderDTOPage = new Page<>();
        BeanUtils.copyProperties(busiOrderEntityPage, busiOrderDTOPage);
        return busiOrderDTOPage;
    }

    @Override
    @Transactional
    public void saveOrder(BusiOrderDTO dto) {
        //--------------------------------业务校验--------------------------------
        if (dto.getSupplyNum() == null || dto.getSupplyNum().compareTo(new BigDecimal("0")) == 0) {
            throw new CustomException("率约量不允许为0!");
        }
        //校验: 工厂不能创建订单
        SysTenantEntity sysTenantEntity = sysTenantDao.selectById(Optional.ofNullable(SecurityUser.getTenantId()).orElseThrow(() -> new CustomException("没有租户信息!")));
        if (Optional.ofNullable(sysTenantEntity).orElseThrow(() -> new CustomException("未查询到指定客户信息")).getTenantType() == 0)
            throw new CustomException("工厂不能创建订单!");
        //不能接自己的单
        if (Objects.equals(dto.getDemandId(), SecurityUser.getTenantId())) throw new CustomException("不能接自己的单");

        //--------------------------------save order--------------------------------
        //物流信息不为空，设置订单状态为已发货; 0: 待发货， 1：已发货
        dto.setStatus(StringUtils.isNotBlank(dto.getDeliveryInfo()) ? 1 : 0);
        dto.setTenantId(SecurityUser.getTenantId());
        dto.setOrderNo(String.valueOf(NumberUtil.generateRandomNumber(1000, 10000, 1)[0]));
        BusiDemandEntity demand = Optional.ofNullable(busiDemandDao.selectOne(new LambdaQueryWrapper<BusiDemandEntity>().eq(BusiDemandEntity::getDemandNo, dto.getDemandNo())))
                .orElseThrow(()->{return new CustomException("查无此需求!");});
        BusiDemandDTO busiDemandDTO = new BusiDemandDTO();
        busiDemandDTO.setId(demand.getId());
        //供应方
        dto.setSupplyId(SecurityUser.getTenantId());
        dto.setSupplyName(sysTenantService.get(SecurityUser.getTenantId()).getName());
        //需求方
        dto.setDemandId(demand.getDemandId());
        dto.setDemandName(sysTenantService.get(demand.getDemandId()).getName());
        //甲方id
        dto.setPaId(demand.getTenantId());
        dto.setPaName(sysTenantService.get(demand.getTenantId()).getName());

        //--------------------------------update demand--------------------------------
        //未履约
        int flag = demand.getDemandTotal().compareTo(demand.getAlreadySupplyNum() == null ? dto.getSupplyNum() : demand.getAlreadySupplyNum().add(dto.getSupplyNum()));
        if (flag == 0) {
            //已完成
            busiDemandDTO.setDemandStatus(3);
            //查询出该需求下的所有订单
        } else if(flag < 0){
            throw new CustomException("供应超量!");
        }
        busiDemandDTO.setPerformanceId(StringUtils.isNotBlank(demand.getPerformanceId()) ? demand.getPerformanceId() + "," + SecurityUser.getTenantId()
                : String.valueOf(SecurityUser.getTenantId()));
        //总需求量 > 供应量
        busiDemandDTO.setAlreadySupplyNum(Optional.ofNullable(demand.getAlreadySupplyNum()).orElseGet(() -> {
            return new BigDecimal("0.0");
        }).add(dto.getSupplyNum()));


        //save 地址, 发票抬头, 货品 snapshot, 供应方，需求方
        dto.setAddressId(this.saveAddrSnapshot(dto.getAddressId()));
        dto.setProductId(this.saveProductSnapshot(dto.getProductId()));
        dto.setInvoiceHeadId(this.saveInvoiceHeadSnapshot(dto.getInvoiceHeadId()));
        dto.setDemandName(sysTenantService.get(demand.getTenantId()).getName());
        dto.setSupplyName(sysTenantService.get(SecurityUser.getTenantId()).getName());
        dto.setProductUnit(demand.getProductUnit());
        save(dto);
        busiDemandService.update(busiDemandDTO);
    }


    /**
     * @param id
     * @desc
     */
    private Long saveInvoiceHeadSnapshot(Long id) {
        try {
            BusiDemandInvoiceHeadSnapshotDTO busiInvoiceHeadDTO = Optional.ofNullable(demandInvoiceHeadSnapshotService.get(id))
                            .orElseThrow(()->{return new CustomException("找不到发票抬头数据");});
            BusiOrderInvoiceHeadSnapshotDTO invoiceHeadSnapshotDTO = new BusiOrderInvoiceHeadSnapshotDTO();
            BeanUtils.copyProperties(busiInvoiceHeadDTO, invoiceHeadSnapshotDTO);
            invoiceHeadSnapshotDTO.setId(null);
            invoiceHeadSnapshotDTO.setInvoiceHeadId(busiInvoiceHeadDTO.getId());
            invoiceHeadSnapshotService.save(invoiceHeadSnapshotDTO);
            return invoiceHeadSnapshotDTO.getId();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new CustomException("插入订单发票抬头快照异常!");
        }
    }


    /**
     * @param id
     * @desc
     */
    private Long saveAddrSnapshot(Long id) {
        try {
            BusiDemandAddressSnapshotDTO busiAddressDTO = Optional.ofNullable(demandAddressSnapshotService.get(id))
                    .orElseThrow(() -> {
                        return new CustomException("未找到地址数据");
                    });
            BusiOrderAddressSnapshotDTO addressSnapshotDTO = new BusiOrderAddressSnapshotDTO();
            BeanUtils.copyProperties(busiAddressDTO, addressSnapshotDTO);
            addressSnapshotDTO.setId(null);
            addressSnapshotDTO.setAddressId(busiAddressDTO.getId());
            addrShotService.save(addressSnapshotDTO);
            return addressSnapshotDTO.getId();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new CustomException("插入订单地址快照异常!");
        }
    }

    /**
     * @param id
     * @desc
     */
    private Long saveProductSnapshot(Long id) {
        try {
            BusiDemandProductSnapshotDTO sysProductDTO = Optional.ofNullable(demandProductSnapshotService.get(id))
                    .orElseThrow(()-> {return new CustomException("未找到货品数据");});
            SysOrderProductSnapshotDTO addressSnapshotDTO = new SysOrderProductSnapshotDTO();
            BeanUtils.copyProperties(sysProductDTO, addressSnapshotDTO);
            addressSnapshotDTO.setId(null);
            addressSnapshotDTO.setProductId(sysProductDTO.getId());

            SysProductDTO productDetail = sysProductService.getDetail(sysProductDTO.getProductId());
            addressSnapshotDTO.setFirstParentId(productDetail.getFirstParentId());
            addressSnapshotDTO.setFirstParentName(productDetail.getFirstParentName());
            addressSnapshotDTO.setSecondParentId(productDetail.getSecondParentId());
            addressSnapshotDTO.setSecondParentName(productDetail.getSecondParentName());
            productSnapshotService.save(addressSnapshotDTO);
            return addressSnapshotDTO.getId();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new CustomException("插入订单货品快照异常!");
        }
    }


    public void concurrentSaveOrder(BusiOrderDTO dto) {
        if (dto.getSupplyNum() == null || dto.getSupplyNum().compareTo(new BigDecimal("0")) == 0) {
            throw new CustomException("率约量不允许为0!");
        }
        //工厂不能创建订单
        SysTenantEntity sysTenantEntity = sysTenantDao.selectById(Optional.ofNullable(SecurityUser.getTenantId()).orElseThrow(() -> new CustomException("没有租户信息!")));
        if (Optional.ofNullable(sysTenantEntity).orElseThrow(() -> new CustomException("未查询到指定客户信息")).getTenantType() == 0)
            throw new CustomException("工厂不能创建订单!");
        //不能接自己的单
        if (Objects.equals(dto.getDemandId(), SecurityUser.getTenantId())) throw new CustomException("不能接自己的单");
        //物流信息不为空，设置订单状态为已发货
        //0: 待发货， 1：已发货
        dto.setStatus(StringUtils.isNotBlank(dto.getDeliveryInfo()) ? 1 : 0);
        //供应方
        dto.setSupplyId(SecurityUser.getTenantId());
        //租户
        dto.setTenantId(SecurityUser.getTenantId());
        dto.setOrderNo(String.valueOf(NumberUtil.generateRandomNumber(1000, 10000, 1)[0]));
        //需求方id
        dto.setDemandId(dto.getTenantId());
        //更新需求
        this.casSAUDemandByNo(dto);
//        this.concurrentSAUDemandByNo(dto);
        save(dto);
    }

    @Override
    public void close(List<BusiOrderDTO> dtos) {
        try {
            List<BusiOrderEntity> busiOrderEntities = ConvertUtils.sourceToTarget(dtos, BusiOrderEntity.class);
            updateBatchById(busiOrderEntities);
        }catch (Exception e){
            log.error(e.getMessage(), e);
            throw new CustomException("关单失败");
        }

//        try {
//            LambdaQueryWrapper<BusiOrderEntity> updatequery = new LambdaQueryWrapper<BusiOrderEntity>()
//                    .in(BusiOrderEntity::getId, ids).eq(BusiOrderEntity::getDeleted, 0);
//            int update = busiOrderDao.update(BusiOrderEntity.builder().status(3).build(), updatequery);
//            if(update == 0) throw new CustomException("更新记录数为0");
//        }catch (Exception e){
//            log.error(e.getMessage(), e);
//            throw e;
//        }
    }

    private boolean casSAUDemandByNo(BusiOrderDTO order) {
        /**
         * CAS: select demand -> 业务逻辑 -> update demand where suppllyNum = old
         *      失败
         */
        BusiDemandEntity demand;
        try {
            //select demand by demandNo
            demand = busiDemandDao.selectOne(new LambdaQueryWrapper<BusiDemandEntity>().eq(BusiDemandEntity::getDemandNo, order.getDemandNo()));
            //create demand update object
            BusiDemandEntity updateDemandObject = createUpdateDemandObject(demand, order.getSupplyNum());
            if (updateDemandObject != null) {
                //update demand by id
                int updateRows = busiDemandDao.update(updateDemandObject, new LambdaQueryWrapper<BusiDemandEntity>().eq(BusiDemandEntity::getId, updateDemandObject.getId())
                        .eq(BusiDemandEntity::getAlreadySupplyNum, updateDemandObject.getAlreadySupplyNum()));
                if (updateRows == 0) {
                    //递归自旋, 怎么加时效
                    casSAUDemandByNo(order);
                }
            }
        } catch (Exception e) {
            log.error(e.getMessage());
            return false;
        }
        return true;

    }

    /**
     * 组装, 更新需求对象
     *
     * @param demand
     * @param supplyNum
     * @return
     */
    private BusiDemandEntity createUpdateDemandObject(BusiDemandEntity demand, BigDecimal supplyNum) {
        BusiDemandEntity updateDemandObject = new BusiDemandEntity();
        updateDemandObject.setId(demand.getId());
        try {
            int flag = demand.getDemandTotal().compareTo(demand.getAlreadySupplyNum() == null ? supplyNum : demand.getAlreadySupplyNum().add(supplyNum));
            if (flag > 0) {
                //更新需求状态: 未履约
                updateDemandObject.setDemandStatus(1);
            } else if (flag == 0) {
                //更新需求状态: 履约中
                updateDemandObject.setDemandStatus(2);
                //查询出该需求下的所有订单
                LambdaQueryWrapper<BusiOrderEntity> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.in(BusiOrderEntity::getDemandNo, demand.getDemandNo());
                List<BusiOrderEntity> busiOrderEntities = busiOrderDao.selectList(queryWrapper);
                if (busiOrderEntities != null && busiOrderEntities.size() != 0) {
                    boolean mark = true;
                    for (BusiOrderEntity busiOrderEntity : busiOrderEntities) {
                        mark = StringUtils.isNotBlank(busiOrderEntity.getDeliveryInfo());
                    }
                    //更新需求状态: 如果,需求量等于供应量,且全部发货
                    if (mark) updateDemandObject.setDemandStatus(3);
                }
            } else {
                throw new CustomException("供应超量!");
            }
            demand.setPerformanceId(demand.getPerformanceId() == null ? SecurityUser.getTenantId().toString()
                    : demand.getPerformanceId() + "," + SecurityUser.getTenantId());
            //总需求量 > 供应量
            updateDemandObject.setAlreadySupplyNum(Optional.ofNullable(demand.getAlreadySupplyNum()).orElseGet(() -> {
                return new BigDecimal("0.0");
            }).add(supplyNum));
        } catch (Exception e) {
            log.error(e.getMessage());
            return null;
        }
        return updateDemandObject;
    }

    private synchronized boolean concurrentSAUDemandByNo(BusiOrderDTO order) {
        BusiDemandEntity demand;
        try {
            demand = busiDemandDao.selectOne(new LambdaQueryWrapper<BusiDemandEntity>().eq(BusiDemandEntity::getDemandNo, order.getDemandNo()));
            BusiDemandDTO updateDemandObject = new BusiDemandDTO();
            updateDemandObject.setId(order.getDemandId());
            int flag = demand.getDemandTotal().compareTo(demand.getAlreadySupplyNum() == null ? order.getSupplyNum() : demand.getAlreadySupplyNum().add(order.getSupplyNum()));
            if (flag > 0) {
                //更新需求状态: 未履约
                updateDemandObject.setDemandStatus(1);
            } else if (flag == 0) {
                //更新需求状态: 履约中
                updateDemandObject.setDemandStatus(2);
                //查询出该需求下的所有订单
                LambdaQueryWrapper<BusiOrderEntity> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.in(BusiOrderEntity::getDemandNo, demand.getDemandNo());
                List<BusiOrderEntity> busiOrderEntities = busiOrderDao.selectList(queryWrapper);
                if (busiOrderEntities != null && busiOrderEntities.size() != 0) {
                    boolean mark = true;
                    for (BusiOrderEntity busiOrderEntity : busiOrderEntities) {
                        mark = StringUtils.isNotBlank(busiOrderEntity.getDeliveryInfo());
                    }
                    //更新需求状态: 如果,需求量等于供应量,且全部发货
                    if (mark) updateDemandObject.setDemandStatus(3);
                }
            } else {
                throw new CustomException("供应超量!");
            }
            demand.setPerformanceId(demand.getPerformanceId() == null ? SecurityUser.getTenantId().toString()
                    : demand.getPerformanceId() + "," + SecurityUser.getTenantId());
            //总需求量 > 供应量
            updateDemandObject.setAlreadySupplyNum(Optional.ofNullable(demand.getAlreadySupplyNum()).orElseGet(() -> {
                return new BigDecimal("0.0");
            }).add(order.getSupplyNum()));
            busiDemandService.update(updateDemandObject);
        } catch (Exception e) {
            log.error(e.getMessage());
            return false;
        }
        return true;
    }

    private Map<String, String> dict(String type) {
        try {
            SysDictTypeEntity sysDictTypeEntity = sysDictTypeDao.selectOne(new LambdaQueryWrapper<SysDictTypeEntity>().eq(SysDictTypeEntity::getDictType, type));
            HashMap<String, Object> map = new HashMap<>();
            map.put("dictTypeId", sysDictTypeEntity.getId().toString());
            PageData<SysDictDataDTO> page = sysDictDataService.page(map);
            List<SysDictDataDTO> list = page.getList();
            return list.stream().collect(Collectors.toMap(SysDictDataDTO::getDictValue, SysDictDataDTO::getDictLabel));
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

}